package com.xlx.openLink.base;

import org.thymeleaf.util.StringUtils;

import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;

/**
 * @author seven
 * @create 2018-11-06 14:01
 **/
public class DateUtils {

    public static final String PATTERN_DATE = "yyyy-MM-dd";

    public static final String PATTERN_DATE2 = "MM-dd";

    public static final String PATTERN_DATETIME = "yyyy-MM-dd HH:mm:ss";

    public static final String PATTERN_DATETIME_IOS8601 = "yyyy-MM-dd'T'HH:mm:ss'Z'";

    public static Date date(int year, int month, int day) {
        return date(year, month, day, 0, 0, 0);
    }

    public static Date date(int year, int month, int day, int hour, int minute, int second) {
        Calendar calendar = Calendar.getInstance();
        calendar.setLenient(false);
        calendar.set(year, month, day, hour, minute, second);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    public static Date getOneDayEndTime(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(Calendar.HOUR_OF_DAY, 23);
        cal.set(Calendar.MINUTE, 59);
        cal.set(Calendar.SECOND, 59);
        cal.set(Calendar.MILLISECOND, 999);

        return cal.getTime();
    }

    public static Date getOneDayEndTimeNoMill(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(Calendar.HOUR_OF_DAY, 23);
        cal.set(Calendar.MINUTE, 59);
        cal.set(Calendar.SECOND, 59);
        return cal.getTime();
    }

    public static String getOneDay(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(Calendar.HOUR_OF_DAY, 23);
        DateFormat dateFormat = new SimpleDateFormat(PATTERN_DATE);
        return dateFormat.format(cal.getTime());
    }

    public static Date getOneDayStartTime(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MILLISECOND, 0);

        return cal.getTime();
    }

    public static Date getOneDayStartTimeNoMill(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);

        return cal.getTime();
    }

    public static Date parseDate(String string, String pattern) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat(pattern);
        sdf.setLenient(false);
        return sdf.parse(string);
    }

    public static Date parseDate(String string, String pattern, TimeZone timeZone) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat(pattern);
        sdf.setTimeZone(timeZone);
        sdf.setLenient(false);
        return sdf.parse(string);
    }

    public static int getWeekOfDateNum(Date dt) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(dt);
        int w = cal.get(Calendar.DAY_OF_WEEK) - 1;
        if (w < 0) {
            w = 0;
        }
        return w;
    }

    public static String getWeekOfDate(Date dt) {
        String[] weekDays = {"星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"};
        int w = getWeekOfDateNum(dt);
        return weekDays[w];
    }

    /**
     * <b>获取(中国人习惯)本周星期一：formatted as yyyy-MM-dd</b>
     *
     * @return
     */
    public static String getMondayOfWeek() {
        return getMondayOfWeek(new Date(), PATTERN_DATE);
    }

    /**
     * <b>获取(中国人习惯)星期一：根据指定日期和日期模式</b>
     *
     * @param date    日期
     * @param pattern 日期模式
     * @return
     */
    public static String getMondayOfWeek(Date date, String pattern) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        DateFormat dateFormat = new SimpleDateFormat(pattern);
        calendar.setFirstDayOfWeek(Calendar.MONDAY);
        int dayWeek = calendar.get(Calendar.DAY_OF_WEEK);
        if (1 == dayWeek) {
            calendar.add(Calendar.DAY_OF_MONTH, -1);
        }
        int day = calendar.get(Calendar.DAY_OF_WEEK);
        calendar.add(Calendar.DATE, calendar.getFirstDayOfWeek() - day);
        return dateFormat.format(calendar.getTime());
    }

    /**
     * <b>获取(中国人习惯)本周星期天：formatted as yyyy-MM-dd</b>
     *
     * @return
     */
    public static String getSundayOfWeek() {
        return getSundayOfWeek(new Date(), PATTERN_DATE);
    }

    /**
     * <b>获取(中国人习惯)星期天：根据指定日期和日期模式</b>
     *
     * @param date    日期
     * @param pattern 日期模式
     * @return
     */
    public static String getSundayOfWeek(Date date, String pattern) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        DateFormat dateFormat = new SimpleDateFormat(pattern);
        calendar.setFirstDayOfWeek(Calendar.MONDAY);
        int dayWeek = calendar.get(Calendar.DAY_OF_WEEK);
        if (1 == dayWeek) {
            calendar.add(Calendar.DAY_OF_MONTH, -1);
        }
        int day = calendar.get(Calendar.DAY_OF_WEEK);
        calendar.add(Calendar.DATE, calendar.getFirstDayOfWeek() - day + 6);
        return dateFormat.format(calendar.getTime());
    }

    /**
     * <b>获取本月第一天：formatted as yyyy-MM-dd</b>
     *
     * @return
     */
    public static String getFirstDayOfMonth() {
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.DATE, 1);
        DateFormat dateFormat = new SimpleDateFormat(PATTERN_DATE);
        return dateFormat.format(calendar.getTime());
    }

    /**
     * <b>获取本月第一天：</b>
     *
     * @param date    日期
     * @param pattern 日期模式
     * @return
     */
    public static String getFirstDayOfMonth(Date date, String pattern) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.DATE, 1);
        DateFormat dateFormat = new SimpleDateFormat(pattern);
        return dateFormat.format(calendar.getTime());
    }

    /**
     * <b>获取本月最后一天：formatted as yyyy-MM-dd</b>
     *
     * @return
     */
    public static String getLastDayOfMonth() {
        Calendar calendar = Calendar.getInstance();
        DateFormat dateFormat = new SimpleDateFormat(PATTERN_DATE);
        calendar.set(Calendar.DATE, 1);
        calendar.roll(Calendar.DATE, -1);
        return dateFormat.format(calendar.getTime());
    }

    /**
     * <b>获取本月最后一天：</b>
     *
     * @param date    日期
     * @param pattern 日期模式
     * @return
     */
    public static String getLastDayOfMonth(Date date, String pattern) {
        Calendar calendar = Calendar.getInstance();
        DateFormat dateFormat = new SimpleDateFormat(pattern);
        calendar.setTime(date);
        calendar.set(Calendar.DATE, 1);
        calendar.roll(Calendar.DATE, -1);
        return dateFormat.format(calendar.getTime());
    }

    public static Date addDays(Date date, int amount) {
        return add(date, Calendar.DAY_OF_MONTH, amount);
    }

    public static Date addWeeks(Date date, int amount) {
        return add(date, Calendar.WEEK_OF_YEAR, amount);
    }

    public static Date addMonths(Date date, int amount) {
        return add(date, Calendar.MONTH, amount);
    }

    public static Date addYears(Date date, int amount) {
        return add(date, Calendar.YEAR, amount);
    }

    public static Date addHours(Date date, int amount) {
        return add(date, Calendar.HOUR_OF_DAY, amount);
    }

    public static Date addMinutes(Date date, int amount) {
        return add(date, Calendar.MINUTE, amount);
    }

    public static Date addSeconds(Date date, int amount) {
        return add(date, Calendar.SECOND, amount);
    }

    public static Date addMilliseconds(Date date, int amount) {
        return add(date, Calendar.MILLISECOND, amount);
    }

    /**
     * 给时间加上或减去指定毫秒，秒，分，时，天、月或年等，返回变动后的时间
     *
     * @param date   要加减前的时间，如果不传，则为当前日期 * Calendar.HOUR,Calendar.DATE, Calendar.MONTH,Calendar.YEAR
     * @param amount 按指定时间域加减的时间数量，正数为加，负数为减。
     * @return 变动后的时间
     */
    private static Date add(Date date, int calendarField, int amount) {
        if (date == null) {
            throw new IllegalArgumentException("The date must not be null");
        }
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.add(calendarField, amount);
        return c.getTime();
    }

    /**
     * 格式化日期
     *
     * @param date 要格式化的日期
     * @param fs   日期格式，使用常量
     * @return 格式化后的日期
     */
    public static String formatDate(Date date, DateEnum fs) {
        DateEnum pattern = fs;
        if (date == null) {
            return "";
        }
        if (fs == null) {
            // 默认YYYY-MM-DD格式
            pattern = DateEnum.YYYYMMDD_BYSEP;
        }
        // 设定格式
        SimpleDateFormat sdf = new SimpleDateFormat(pattern.getValue());
        // 返回最终格式
        return sdf.format(date);
    }

    /**
     * 格式当前日期
     *
     * @return 格式化后的日期
     */
    public static String getNow(DateEnum fs) {
        return formatDate(now(), fs);
    }

    /**
     * 将字符串格式化为日期
     *
     * @param date 日期字符串
     * @param fs   日期格式
     * @return 日期
     */
    public static Date parseDate(String date, DateEnum fs) {
        if (date == null || date.length() == 0) {
            return null;
        }
        // 日期格式
        SimpleDateFormat formatter = new SimpleDateFormat(fs.getValue());
        try {
            return formatter.parse(date);
        } catch (ParseException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * @param date
     * @param pattern
     * @return
     */
    public static String formatDate(Date date, String pattern) {
        String format = pattern;
        if (date == null) {
            return "";
        }
        if (pattern == null) {
            format = "yyyy-MM-dd";
        }
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        return sdf.format(date);
    }

    public static String formatDate(Date date, String pattern, TimeZone timeZone) {
        String format = pattern;
        if (date == null) {
            return "";
        }
        if (pattern == null) {
            format = "yyyy-MM-dd";
        }
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        sdf.setTimeZone(timeZone);
        return sdf.format(date);
    }

    /**
     * @param date
     * @return
     */
    public static String formatDateTime(Date date) {
        return formatDate(date, "yyyy-MM-dd HH:mm:ss");
    }

    /**
     * 以前yyyy-MM-dd HH:mm:ss刘柱更改yyyyMMddHHmmssSSS
     *
     * @return
     */
    public static String formatDateTime() {
        return formatDate(now(), "yyyyMMddHHmmssSSS");
    }

    public static String formatDateTime2() {
        return formatDate(now(), "yyyyMMddHHmmss");
    }

    /**
     * 转换一个日期精确到毫秒
     *
     * @return
     */
    public static String formatDateTimeMms(Date date) {
        return formatDate(date, "yyyy-MM-dd HH:mm:ss.SSS");
    }

    public static String formatDate(Date date) {
        return formatDate(date, "yyyy-MM-dd");
    }

    public static String formatDate2(Date date) {
        return formatDate(date, "yyyyMMdd");
    }

    public static String formatDate() {
        return formatDate(now(), "yyyy-MM-dd");
    }

    public static String formatDate2() {
        return formatDate(now(), "yyyyMMdd");
    }

    public static String formatTime(Date date) {
        return formatDate(date, "HH:mm:ss");
    }

    public static String formatTime() {
        return formatDate(now(), "HH:mm:ss");
    }

    public static String formatTime2() {
        return formatDate(now(), "HHmmss");
    }

    public static Date now() {
        return new Date();
    }

    public static Date parseDateTime(String datetime) {
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        if ((datetime == null) || ("".equals(datetime))) {
            return null;
        } else {
            try {
                return formatter.parse(datetime);
            } catch (ParseException e) {
                return parseDate(datetime);
            }
        }
    }

    public static Date parseDate(String date) {
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
        if ((date == null) || ("".equals(date))) {
            return null;
        } else {
            try {
                return formatter.parse(date);
            } catch (ParseException e) {
                return null;
            }
        }
    }

    public static Date parseDate2(String date) {
        SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMdd");
        if ((date == null) || ("".equals(date))) {
            return null;
        } else {
            try {
                return formatter.parse(date);
            } catch (ParseException e) {
                return null;
            }
        }
    }

    public static Date parseDate(Date datetime) {
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
        if (datetime == null) {
            return null;
        } else {
            try {
                return formatter.parse(formatter.format(datetime));
            } catch (ParseException e) {
                return null;
            }
        }
    }

    public static String formatDate(Object o) {
        if (o == null) {
            return "";
        }
        if (o.getClass() == String.class) {
            return formatDate(o);
        } else if (o.getClass() == Date.class) {
            return formatDate(o);
        } else if (o.getClass() == Timestamp.class) {
            return formatDate(new Date(((Timestamp) o).getTime()));
        } else {
            return o.toString();
        }
    }

    public static String formatDateTime(Object o) {
        if (o.getClass() == String.class) {
            return formatDateTime(o);
        } else if (o.getClass() == Date.class) {
            return formatDateTime(o);
        } else if (o.getClass() == Timestamp.class) {
            return formatDateTime(new Date(((Timestamp) o).getTime()));
        } else {
            return o.toString();
        }
    }

    public static Date addMilliSecond(Date date, int amount) {
        return add(date, Calendar.MILLISECOND, amount);
    }

    public static Date addSecond(Date date, int amount) {
        return add(date, Calendar.SECOND, amount);
    }

    public static Date addMiunte(Date date, int amount) {
        return add(date, Calendar.MINUTE, amount);
    }

    public static Date addHour(Date date, int amount) {
        return add(date, Calendar.HOUR, amount);
    }

    public static Date addDay(Date date, int amount) {
        return add(date, Calendar.DATE, amount);
    }

    public static Date addMonth(Date date, int amount) {
        return add(date, Calendar.MONTH, amount);
    }

    public static Date addYear(Date date, int amount) {
        return add(date, Calendar.YEAR, amount);
    }

    public static Date getDate() {
        return parseDate(formatDate2());
    }

    public static Date getDateTime() {
        return parseDateTime(formatDateTime());
    }

    /**
     * 日期格式转换,从YYYYMMdd格式转换成YYYY-MM-dd
     *
     * @param dateString
     * @return
     */
    public static String parseDateString(String dateString) {
        return formatDate(parseDate2(dateString));
    }

    public static String formatTimeStamp(String dat, String tim, int len) {
        SimpleDateFormat df = new SimpleDateFormat(dat);
        if (tim.length() > len) {
            return df.format(Long.valueOf(tim));
        }
        return tim;
    }

    public static String formateDate(String dateTime) {
        if (dateTime == null || "".equals(dateTime)) {
            return "";
        }
        return dateTime.substring(0, 4) + "年" + dateTime.substring(4, 6) + "月" + dateTime.substring(6, 8) + "日 " + dateTime.substring(8, 10) + ":"
                + dateTime.substring(10, 12) + ":" + dateTime.substring(12, 14);
    }

    public static String secToTime(int time) {
        String timeStr = null;
        int hour = 0;
        int minute = 0;
        int second = 0;
        if (time <= 0) {
            return "00:00";
        } else {
            minute = time / 60;
            if (minute < 60) {
                second = time % 60;
                timeStr = unitFormat(minute) + ":" + unitFormat(second);
            } else {
                hour = minute / 60;
                minute = minute % 60;
                second = time - hour * 3600 - minute * 60;
                timeStr = unitFormat(hour) + ":" + unitFormat(minute) + ":" + unitFormat(second);
                timeStr = (hour > 99) ? "99:59:59" : timeStr;
            }
        }
        return timeStr;
    }

    public static String unitFormat(int i) {
        String retStr = null;
        if (i >= 0 && i < 10) {
            retStr = "0" + Integer.toString(i);
        } else {
            retStr = "" + i;
        }
        return retStr;
    }

    /**
     * 此方法默认输入的时间为东八区的时间, 用于solr的时间转换
     *
     * @param dateStr
     * @return
     */
    public static String formatIOS8601(String dateStr) {
        return formatIOS8601(dateStr, false);
    }

    public static String formatIOS8601(String dateStr, boolean addOneDay) {
        if (StringUtils.isEmpty(dateStr)) {
            throw new RuntimeException("parse date error, date is empty");
        }
        Date date = null;
        if (StringUtils.length(dateStr) == 10) {
            date = parseISO8601(dateStr, PATTERN_DATE);
        } else if (StringUtils.length(dateStr) == 19) {
            date = parseISO8601(dateStr, PATTERN_DATETIME);
        }
        if (date == null) {
            throw new RuntimeException("parse date error, date length error. ");
        }

        Calendar instance = Calendar.getInstance();
        instance.setTime(date);
        instance.add(Calendar.HOUR, -8);
        if (addOneDay) {
            instance.add(Calendar.DATE, 1);
        }

        date = instance.getTime();
        // PATTERN_DATETIME_IOS8601
        return formatDate(date, PATTERN_DATETIME_IOS8601);
    }

    /**
     * 此方法默认输入的时间为东八区的时间, 用于solr的时间转换
     *
     * @param dateStr
     * @param pattern
     * @return
     */
    public static Date parseISO8601(String dateStr, String pattern) {
        try {
            return parseDate(dateStr, pattern, TimeZone.getTimeZone("GMT+8"));
        } catch (ParseException e) {
            return null;
        }
    }

    /**
     * 比较两个时间的大小
     *
     * @param time1
     * @param time2
     * @return 0 时间相等 0< time1小于time2，>0 time1大于time2
     */
    public static Integer compareTiems(Date time1, Date time2) {
        if (time1 == null || time2 == null) {
            return null;
        }

        Calendar c1 = Calendar.getInstance();
        Calendar c2 = Calendar.getInstance();

        c1.setTime(time1);
        c2.setTime(time2);

        return c1.compareTo(c2);
    }

    /**
     * 返回两个日期之间的天数
     *
     * @param begin
     * @param end
     * @return
     */
    public static int dateDiffByDay(Date begin, Date end) {
        return (int) ((end.getTime() - begin.getTime()) / 24 / 3600000);
    }

    /**
     * 返回两个日期之间的秒数
     *
     * @param begin
     * @param end
     * @return
     */
    public static int dateDiffBySec(Date begin, Date end) {
        return (int) ((end.getTime() - begin.getTime()) / 1000);
    }

    /**
     * 返回毫秒数
     *
     * @param begin
     * @param end
     * @return
     */
    public static int dateDiffByMsec(Date begin, Date end) {
        return (int) ((end.getTime() - begin.getTime()));
    }

    /**
     * 返回两个日期之间的分钟数
     *
     * @param begin
     * @param end
     * @return
     */
    public static int dateDiffByMinute(Date begin, Date end) {
        return (int) ((end.getTime() - begin.getTime()) / 1000 / 60);
    }

    /**
     * 返回两个日期之间的小时数
     *
     * @param begin
     * @param end
     * @return
     */
    public static int dateDiffByHour(Date begin, Date end) {
        return (int) ((end.getTime() - begin.getTime()) / 1000 / 3600);
    }
}
